package cn.tedu.charging.cost.service;

import cn.tedu.charging.common.pojo.param.ChargingProgressParam;
import cn.tedu.charging.common.pojo.po.ChargingCostRulePO;
import cn.tedu.charging.common.pojo.vo.ChargingProgressVO;
import cn.tedu.charging.cost.repository.CostRuleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;

@Service
@Slf4j
public class CostRuleService {
    @Autowired
    private CostRuleRepository costRuleRepository;
    @Autowired
    private StringRedisTemplate redisTemplate;//incrby 计步器 需要客户端对value使用string序列化
    public ChargingProgressVO costCalc(ChargingProgressParam param) {
        //1.使用参数中的gunId 查询枪的类型type
        Integer gunType=getGunTypeByGunId(param.getUserId());
        //2.调用仓储层 查询符合stationsId 符合 gunType 符合 当前系统时间的计价规则
        ChargingCostRulePO chargingCostRulePO =getCostRule(param,gunType, LocalDateTime.now().getHour());
        //3.不使用double计算带有小数点 带有整数转化的金额 使用BigDecimal 得到本次计算金额
        BigDecimal cost=calculatePrice(chargingCostRulePO,param);
        //4.计算得到本次金额的累加结果
        BigDecimal totalCost=calculateToalPrice(param,cost);
        //5.封装vo
        return assembleProgressVO(param, chargingCostRulePO,totalCost);
    }

    private ChargingProgressVO assembleProgressVO(ChargingProgressParam param, ChargingCostRulePO chargingCostRulePO, BigDecimal totalCost) {
        ChargingProgressVO vo=new ChargingProgressVO();
        BeanUtils.copyProperties(param,vo);
        vo.setPowerFee(chargingCostRulePO.getPowerFee());
        vo.setTotalCost(totalCost);
        return vo;
    }

    private BigDecimal calculateToalPrice(ChargingProgressParam param, BigDecimal cost) {
        //1.将本次金额 2个小数点 乘以100 取整数 放到redis迭代
        int costInt = cost.multiply(new BigDecimal(100)).intValue();
        //2.调用string数据类型客户端 做incrment操作
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        //每张订单 独一无二的,所以计价叠加 每张订单一个key值
        String billKey="charging:cost:bill:"+param.getBillId();
        Long increment = opsForValue.increment(billKey, costInt);
        //将long转化成bigDeimal,取两位小数点 乘法是multiply 除法divide
        //取小数点后几位的规则 RoundingMode
        //RoundingMode.HALF_UP 四舍五入 2位  1.986 ~ 1.99 1.982 ~1.98
        //RoundingMode.HALF_DOWN; 五舍六入
        //RoundingMode.FLOOR 直接将后面 删掉 2位 1.986~1.98 1.989~1.98
        //RoundingMode.CEILING 取天花板 后面只要不是0 直接进位 2位 1.986 ~1.99 1.98001~1.99
        BigDecimal totalCost = new BigDecimal(increment).divide(new BigDecimal(100)).setScale(2, RoundingMode.FLOOR);
        log.info("本次订单累计金额:{}",totalCost);
        return totalCost;
    }

    private BigDecimal calculatePrice(ChargingCostRulePO chargingCostRulePO, ChargingProgressParam param) {
        //使用充电度数 乘以 power_fee单价
        Float chargingCapacity = param.getChargingCapacity();//1.58
        BigDecimal powerFee = chargingCostRulePO.getPowerFee();//1.5
        //使用BigDecimal的api 按照2位小数点进行四舍五入
        BigDecimal cost = powerFee.multiply(new BigDecimal(chargingCapacity)).setScale(2, RoundingMode.HALF_UP);
        log.info("本次电价:{}",cost);
        return cost;
    }

    private ChargingCostRulePO getCostRule(ChargingProgressParam param, Integer gunType, Integer hour) {
        return costRuleRepository.getCostRule(param.getStationId(),gunType,hour);
    }

    private Integer getGunTypeByGunId(Integer userId) {
        //openFeign远程调用 调用device服务返回枪类型
        return 1;
    }
}
